package org.kabeja.dxf.entity;

import org.kabeja.dxf.DXFConstants;
import org.kabeja.dxf.helpers.Point;
import org.kabeja.dxf.helpers.Vector;
import org.kabeja.math.MathUtils;
import org.kabeja.math.ParametricPlane;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * @author shutao
 * @since 2022/4/25 10:11
 */
public class DXFViewport extends DXFEntity {
    private String viewportID = "";
    private String plotStyleName = "";
    private Point lowerLeftCorner = new Point();
    private Point upperRightCorner = new Point();
    private Point centerPoint = new Point();
    private Point snapBasePoint = new Point();
    private Point snapSpacingPoint = new Point();
    private Point gridSpacingPoint = new Point();
    private Vector viewDirectionVector = new Vector();
    private Point viewCenterPoint = new Point();
    private Point viewTargetPoint = new Point();
    private Vector ucsOrigin = new Vector();
    private Vector ucsXAxis = new Vector();
    private Vector ucsYAxis = new Vector();
    private int ucsType = 0;
    private int viewportStatus = 0;
    private double ucsElevation = 0.0D;
    private boolean useUCS = false;
    private double height;
    private double width;
    private double ratio;
    private double lensLength;
    private double viewHeight;
    private double frontClippingPlane;
    private double backClippingPlane;
    private double twistAngle;
    private double snapAngle;
    private double circleZoom;
    private double fastZoom;
    private boolean snap;
    private boolean grid;
    private boolean active = false;
    private int renderMode;
    private Set<String> frozenLayerSet = new HashSet<>();

    public DXFViewport() {
        this.setLineType(this.getType());
    }

    public double getBackClippingPlane() {
        return this.backClippingPlane;
    }

    public void setBackClippingPlane(double var1) {
        this.backClippingPlane = var1;
    }

    public Point getCenterPoint() {
        return this.centerPoint;
    }

    public void setCenterPoint(Point var1) {
        this.centerPoint = var1;
    }

    public double getCircleZoom() {
        return this.circleZoom;
    }

    public void setCircleZoom(double var1) {
        this.circleZoom = var1;
    }

    public double getFastZoom() {
        return this.fastZoom;
    }

    public void setFastZoom(double var1) {
        this.fastZoom = var1;
    }

    public double getFrontClippingPlane() {
        return this.frontClippingPlane;
    }

    public void setFrontClippingPlane(double var1) {
        this.frontClippingPlane = var1;
    }

    public boolean isGrid() {
        return this.grid;
    }

    public void setGrid(boolean var1) {
        this.grid = var1;
    }

    public Point getGridSpacingPoint() {
        return this.gridSpacingPoint;
    }

    public void setGridSpacingPoint(Point var1) {
        this.gridSpacingPoint = var1;
    }

    public double getHeight() {
        return this.height;
    }

    public void setHeight(double var1) {
        this.height = var1;
    }

    public double getLensLength() {
        return this.lensLength;
    }

    public void setLensLength(double var1) {
        this.lensLength = var1;
    }

    public Point getLowerLeftCorner() {
        return this.lowerLeftCorner;
    }

    public void setLowerLeftCorner(Point var1) {
        this.lowerLeftCorner = var1;
    }

    public String getViewportID() {
        return this.viewportID;
    }

    public void setViewportID(String var1) {
        this.viewportID = var1;
    }

    public double getAspectRatio() {
        return this.ratio;
    }

    public void setAspectRatio(double var1) {
        this.ratio = var1;
    }

    public void setTwistAngle(double var1) {
        this.twistAngle = var1;
    }

    public boolean isSnap() {
        return this.snap;
    }

    public void setSnap(boolean var1) {
        this.snap = var1;
    }

    public Point getSnapBasePoint() {
        return this.snapBasePoint;
    }

    public void setSnapBasePoint(Point var1) {
        this.snapBasePoint = var1;
    }

    public Point getUpperRightCorner() {
        return this.upperRightCorner;
    }

    public void setUpperRightCorner(Point var1) {
        this.upperRightCorner = var1;
    }

    public Vector getViewDirectionVector() {
        return this.viewDirectionVector;
    }

    public void setViewDirectionVector(Vector var1) {
        this.viewDirectionVector = var1;
    }

    public Point getViewCenterPoint() {
        return this.viewCenterPoint;
    }

    public void setViewCenterPoint(Point var1) {
        this.viewCenterPoint = var1;
    }

    public boolean isActive() {
        return this.active;
    }

    public void setActive(boolean var1) {
        this.active = var1;
    }

    @Override
    public Bounds getBounds() {
        Bounds var1 = new Bounds();
        if (this.viewportStatus > 0) {
            var1.addToBounds(this.centerPoint.getX() - this.width / 2.0D, this.centerPoint.getY() - this.height / 2.0D, 0.0D);
            var1.addToBounds(this.centerPoint.getX() + this.width / 2.0D, this.centerPoint.getY() + this.height / 2.0D, 0.0D);
        }

        return var1;
    }

    @Override
    public double getLength() {
        return 0.0D;
    }

    @Override
    public String getType() {
        return DXFConstants.ENTITY_TYPE_VIEWPORT;
    }

    public double getWidth() {
        return this.width;
    }

    public void setWidth(double var1) {
        this.width = var1;
    }

    public void setRenderMode(int var1) {
        this.renderMode = var1;
    }

    public double getViewHeight() {
        return this.viewHeight;
    }

    public void setViewHeight(double var1) {
        this.viewHeight = var1;
    }

    public Vector getUcsOrigin() {
        return this.ucsOrigin;
    }

    public void setUcsOrigin(Vector var1) {
        this.ucsOrigin = var1;
    }

    public Vector getUcsXAxis() {
        return this.ucsXAxis;
    }

    public void setUcsXAxis(Vector var1) {
        this.ucsXAxis = var1;
    }

    public Vector getUcsYAxis() {
        return this.ucsYAxis;
    }

    public void setUcsYAxis(Vector var1) {
        this.ucsYAxis = var1;
    }

    public int getUcsType() {
        return this.ucsType;
    }

    public void setUcsType(int var1) {
        this.ucsType = var1;
    }

    public double getUcsElevation() {
        return this.ucsElevation;
    }

    public void setUcsElevation(double var1) {
        this.ucsElevation = var1;
    }

    public boolean isUseUCS() {
        return this.useUCS;
    }

    public void setUseUCS(boolean var1) {
        this.useUCS = var1;
    }

    public double getRatio() {
        return this.ratio;
    }

    public void setRatio(double var1) {
        this.ratio = var1;
    }

    public int getRenderMode() {
        return this.renderMode;
    }

    public double getSnapAngle() {
        return this.snapAngle;
    }

    public void setSnapAngle(double var1) {
        this.snapAngle = var1;
    }

    public Point getViewTargetPoint() {
        return this.viewTargetPoint;
    }

    public void setViewTargetPoint(Point var1) {
        this.viewTargetPoint = var1;
    }

    public Point getSnapSpacingPoint() {
        return this.snapSpacingPoint;
    }

    public void setSnapSpacingPoint(Point var1) {
        this.snapSpacingPoint = var1;
    }

    public String getPlotStyleName() {
        return this.plotStyleName;
    }

    public void setPlotStyleName(String var1) {
        this.plotStyleName = var1;
    }

    public int getViewportStatus() {
        return this.viewportStatus;
    }

    public void setViewportStatus(int var1) {
        this.viewportStatus = var1;
    }

    public double getTwistAngle() {
        return this.twistAngle;
    }

    public void addFrozenLayer(String var1) {
        this.frozenLayerSet.add(var1);
    }

    public boolean isFrozenLayer(String var1) {
        return this.frozenLayerSet.contains(var1);
    }

    public Iterator getFrozenLayerIterator() {
        return this.frozenLayerSet.iterator();
    }

    public double getZoomXPFactor() {
        return this.viewHeight != 0.0D ? this.height / this.viewHeight : this.calculateZoomXPFactor();
    }

    public double calculateZoomXPFactor() {
        double var1 = this.getViewDirectionVector().getLength() * 42.0D / this.lensLength;
        double var3 = this.width / this.height;
        double var5 = Math.sqrt(Math.pow(var1, 2.0D) / (Math.pow(var3, 2.0D) + 1.0D));
        return this.height / var5;
    }

    public Bounds getModelspaceViewBounds() {
        double var1 = this.width / this.height;
        double var3 = this.height / this.getZoomXPFactor() / 2.0D;
        double var5 = var1 * var3;
        double var10000 = var5 / var3;
        Vector var9 = null;
        if (this.viewDirectionVector.getX() == 0.0D && this.viewDirectionVector.getY() == 0.0D && this.viewDirectionVector.getZ() == 1.0D) {
            var9 = new Vector(1.0D, 0.0D, 0.0D);
        } else {
            var9 = MathUtils.crossProduct(DXFConstants.DEFAULT_Z_AXIS_VECTOR, this.viewDirectionVector);
        }

        ParametricPlane var10 = new ParametricPlane(this.viewTargetPoint, var9, MathUtils.crossProduct(this.viewDirectionVector, var9), this.viewDirectionVector);
        Bounds var11 = new Bounds();
        Point var12 = var10.getPoint(this.viewCenterPoint.getX() - var5, this.viewCenterPoint.getY() - var3);
        var11.addToBounds(var12);
        var12 = var10.getPoint(this.viewCenterPoint.getX() + var5, this.viewCenterPoint.getY() + var3);
        var11.addToBounds(var12);
        return var11;
    }
}
